/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package drt;

import evaluation.Graph;
import evaluation.Vertex;
import java.util.LinkedHashSet;
import java.util.Map;
import logic.Type;

/**
 *
 * @author phong
 */
public class DrtAlphaExpression extends DrtStandAloneExpression {
    
    DrtExpression first;
    DrtExpression second;
    
    public DrtAlphaExpression(DrtExpression func, DrtExpression arg) {
        this.first = func;
        this.second = arg;
        
        if (!this.first.getType().matches(Type.TRUTH_TYPE) || !this.second.getType().matches(Type.TRUTH_TYPE))
            throw new Error("incorrect types");
    }
    
    public DrtExpression getFirst() {
        return this.first;
    }
    
    public DrtExpression getSecond() {
        return this.second;
    }
    
    @Override
    public Type getType() {
        return Type.TRUTH_TYPE;
    }
    
    /*
     * don't use this function
     */
    @Override
    public void setType(Type t) {
    }
    
    @Override
    public void getRefs(LinkedHashSet<DRSReferent> refs) {
        this.first.getRefs(refs);
        this.second.getRefs(refs);
    }
    
    @Override
    public void getAllVariables(LinkedHashSet<DrtVariable> vars) {
        this.first.getAllVariables(vars);
        this.second.getAllVariables(vars);
    }
    
    @Override
    public DrtExpression simplify() {
        DrtExpression fu = this.first.simplify();
        DrtExpression ar = this.second.simplify();
        
        return new DrtAlphaExpression(fu, ar);
    }
    
    @Override
    public DrtAlphaExpression replace(DrtVariable var, DrtExpression exp) {
        return new DrtAlphaExpression(
                first.replace(var, exp), 
                second.replace(var, exp));
    }
    
    @Override
    public String toString() {
        return "(" + this.first.toString() + "A" + this.second.toString() + ")";
    }
    
    @Override
    public boolean equals(Object other) {
        if (other instanceof DrtAlphaExpression) {
            DrtAlphaExpression that = (DrtAlphaExpression)other;
            
            // alpha-convert
            LinkedHashSet<DrtVariable> thisVars = new LinkedHashSet<DrtVariable>();
            this.getAllVariables(thisVars);
            
            DrtAlphaExpression repThat = (DrtAlphaExpression)that.alphaConvert(thisVars);
            if (repThat == null) return false;

            return this.first.equals(repThat.first) && this.second.equals(repThat.second);
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        int hc = "alphaexpression".hashCode();
        if (!(this.first instanceof DrtVariable))
            hc += this.first.hashCode() * 17;
        if (!(this.second instanceof DrtVariable))
            hc += this.second.hashCode() * 31;
        return hc;
    }
    
    @Override
    public Graph toGraph() {
        Graph g = new Graph();
        
        Graph g1 = this.first.toGraph();
        Graph g2 = this.second.toGraph();
        
        for (Vertex v : g1.getMarks()) {
            g.addMarks(v);
        }
        for (Vertex v : g2.getMarks()) {
            g.addMarks(v);
        }
        
        g.merge(g1);
        g.merge(g2);
        
        return g;
    }
    
    @Override
    public DrtAlphaExpression getTemplate(Map<String,String> map) {
        DrtExpression newFirst = this.first.getTemplate(map);
        DrtExpression newSecond = this.second.getTemplate(map);
        return new DrtAlphaExpression(newFirst, newSecond);
    }
}
